import platform
import os
import typing as tp

from pydantic import BaseModel

_IS_WINDOWS = platform.system() == "Windows"


class AgentCFG(BaseModel):
    ROOT: str
    agent_port: int = 56790

    # database
    db_url: str = "sqlite+aiosqlite:///{db_path}"
    alembic_db_url: str = "sqlite:///{db_path}"
    url_args: dict = {}

    # allure_path
    allure_dir: str

    # viztracer
    viztracer_result_json: str = "viztracer_result.html"

    # linux
    linux_passwd: str = None

    user_config: dict = {}

    @property
    def allure_bin_file(self) -> str:
        if not os.path.isabs(self.allure_dir):
            allure_dir = os.path.join(os.getcwd(), self.allure_dir)
        else:
            allure_dir = self.allure_dir
        if platform.system() == "Windows":
            return os.path.join(allure_dir, "bin", "allure.bat")
        else:
            return os.path.join(allure_dir, "bin", "allure")


class GlobalConfig(BaseModel):
    base: AgentCFG
    log_path: str
    tmp_path: str
    task_path: str
    is_windows: bool = _IS_WINDOWS


def _default_create_cfg(
    node: AgentCFG
) -> GlobalConfig:
    return GlobalConfig(
        base=node,
        log_path=os.path.join(node.ROOT, "logs"),
        tmp_path=os.path.join(node.ROOT, "tmp"),
        task_path=os.path.join(node.ROOT, "tasks")
    )


_GLOBAL_CONFIG: tp.Optional[GlobalConfig] = None


def get_config(
    path: str = None
) -> GlobalConfig:
    global _GLOBAL_CONFIG
    if _GLOBAL_CONFIG:
        return _GLOBAL_CONFIG

    meth = _default_create_cfg
    _GLOBAL_CONFIG = meth(AgentCFG.parse_file(path))
    return _GLOBAL_CONFIG
